package learn;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;

/**
 * reentrantLock 是比synchronized更经典的锁
 * 支持可重入，也是可重入 每次都需要自己手动上锁和解锁，若忘记了编译器也不会帮忙
 * reentrantLock是个类用java写的，实现了公平锁  synchronized是个关键字 底层用c++写的,默认是非公平的
 * 公平锁：按线程先来后到的次序依此给锁
 * reentrantLock提供了一个tryLock()方法，返回值时boolean类型，只是看能否获取锁，并不会真正的加锁
 相同点：
 synchronized 和 ReentrantLock 都是 Java 中提供的可重入锁
 不同点：
 用法不同：synchronized 可以用来修饰普通方法、静态方法和代码块；ReentrantLock 只能用于代码块；
 获取和释放锁的机制不同：进入synchronized 块自动加锁和执行完后自动释放锁； ReentrantLock 需要显示的手动加锁和释放锁；
 锁类型不同：synchronized 是非公平锁； ReentrantLock 默认为非公平锁，也可以手动指定为公平锁；
 响应中断不同：synchronized 不能响应中断；ReentrantLock 可以响应中断，可用于解决死锁的问题；
 底层实现不同：synchronized 是 JVM 层面通过监视器实现的；ReentrantLock 是基于 AQS 实现的。
 */
public class reentrantLock_ {

    //AtomicInteger类
    static AtomicInteger atomicInteger = new AtomicInteger();
    static int count = 0;

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                count = atomicInteger.incrementAndGet();//原子类的递增这个值
            }
        });
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 100000; i++) {
                count = atomicInteger.incrementAndGet();//使用这个方法来
            }
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(count);
    }
    public static void main2(String[] args) throws ExecutionException, InterruptedException {
        //Callable 提供返回值得run方法
        int i = 0;
        for (int j = 1; j <= 1000; j++) {
            i += j;
        }
        System.out.println(i);
        Callable<Integer> callable = new Callable() {
            @Override
            public Integer call() throws Exception {
                Integer i = 0;
                for (int j = 1; j <= 1000; j++) {
                    i += j;
                }
                System.out.println("over");
                return i;
            }
        };
//        Thread t1 = new Thread(callable);
//        且没有提供获取返回值的方法那么就需要FutureTask对他包装去获取他的返回值
        FutureTask<Integer> futureTask = new FutureTask(callable);
        Thread t2 = new Thread(futureTask);
//        System.out.println(futureTask.get());
        t2.start();
        System.out.println(futureTask.get());// 调用这个方法后会在awaitDone中死循环等待等待线程结束
//        Thread.sleep(6000);
        System.out.println("main");
    }

    public static void main1(String[] args) throws InterruptedException {
        ReentrantLock r = new ReentrantLock();
        System.out.println(r.tryLock());
        Thread t1 = new Thread(() -> {
            r.lock();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            r.unlock();
        });
        Thread t2 = new Thread(() -> {
            System.out.println(r.tryLock());
            r.lock();
            r.unlock();
        });
        r.wait();
        t1.start();
        Thread.sleep(100);
        t2.start();
    }
}
